package exercises.leetcode;

import java.util.Iterator;

/**
 * <a href="https://leetcode-cn.com/problems/peeking-iterator/">
 * 284. 窥探迭代器</a>
 *
 * <p><span color="#87CEEB">描述:</span>
 * 请你设计一个迭代器，除了支持 hasNext 和 next 操作外，还支持 peek 操作。
 * <p>
 * 实现 PeekingIterator 类：
 * <p>
 * PeekingIterator(int[] nums) 使用指定整数数组 nums 初始化迭代器。
 * int next() 返回数组中的下一个元素，并将指针移动到下个元素处。
 * bool hasNext() 如果数组中存在下一个元素，返回 true ；否则，返回 false 。
 * int peek() 返回数组中的下一个元素，但 不 移动指针。
 *  
 * <p>
 * 示例：
 * <p>
 * 输入：
 * ["PeekingIterator", "next", "peek", "next", "next", "hasNext"]
 * [[[1, 2, 3]], [], [], [], [], []]
 * 输出：
 * [null, 1, 2, 2, 3, false]
 * <p>
 * 解释：
 * PeekingIterator peekingIterator = new PeekingIterator([1, 2, 3]); // [1,2,3]
 * peekingIterator.next();    // 返回 1 ，指针移动到下一个元素 [1,2,3]
 * peekingIterator.peek();    // 返回 2 ，指针未发生移动 [1,2,3]
 * peekingIterator.next();    // 返回 2 ，指针移动到下一个元素 [1,2,3]
 * peekingIterator.next();    // 返回 3 ，指针移动到下一个元素 [1,2,3]
 * peekingIterator.hasNext(); // 返回 False
 *  
 * <p>
 * 提示：
 * <ul>
 * <li>1 <= nums.length <= 1000</li>
 * <li>1 <= nums[i] <= 1000</li>
 * <li>对 next 和 peek 的调用均有效</li>
 * <li>next、hasNext 和 peek 最多调用  1000 次</li>
 * </ul>
 * 进阶：你将如何拓展你的设计？使之变得通用化，从而适应所有的类型，而不只是整数型？
 *
 * @author or2
 * @date 2021年10月05日 时间: 8:47
 */
public class No284 {

    private static class PeekingIterator<E> implements Iterator<E> {
        private final Iterator<E> itr;
        private E nextElement;

        public PeekingIterator(Iterator<E> iterator) {
            this.itr = iterator;
            nextElement = iterator.next();
        }

        // Returns the next element in the iteration without advancing the iterator.
        public E peek() {
            return nextElement;
        }

        // hasNext() and next() should behave the same as in the Iterator interface.
        // Override them if needed.
        @Override
        public E next() {
            E cur =  nextElement;
            nextElement = itr.hasNext() ? itr.next() : null;
            return cur;
        }

        @Override
        public boolean hasNext() {
            return nextElement != null;
        }
    }


    private static class PeekingIterator2 implements Iterator<Integer> {
        private final Iterator<Integer> itr;
        private Integer nextElement;

        public PeekingIterator2(Iterator<Integer> iterator) {
            this.itr = iterator;
            nextElement = iterator.next();
        }

        // Returns the next element in the iteration without advancing the iterator.
        public Integer peek() {
            return nextElement;
        }

        // hasNext() and next() should behave the same as in the Iterator interface.
        // Override them if needed.
        @Override
        public Integer next() {
            Integer cur =  nextElement;
            nextElement = itr.hasNext() ? itr.next() : null;
            return cur;
        }

        @Override
        public boolean hasNext() {
            return nextElement != null;
        }
    }
}
